#include <cstdlib>

#include <getopt.h>

#include <iostream>

#include "bs"

// Tamaño de buffer por defecto: 1M
#define BUFSIZE 1048576

using namespace std;

const char USAGE[] = "\
 [OPTION]...\n\
blocksort or de-blocksort standard input to standard output.\n\n\
  -z                       blocksort (default)\n\
  -x                       de-blocksort (not implemented)\n\
  -b [BUFSIZE]             set buffer size to BUFSIZE (default:1M)\n\
  -v                       verbose, prettyprint blocksort index\n\
  -q                       quiet, do not output blocksort index\n\
  -h                       display this help and quit\
";

int main (int argc, char *argv[]) {
	bool
		compressing = true,
		verbose = false,
		quiet = false,
		help = false,
		fail = false;

	integer bufsize = BUFSIZE;

	for (char c; (c = getopt(argc, argv, "zxb:vqh")) != -1;) {
		switch (c) {
		case 'z': compressing = true; break;
		case 'x': compressing = false; break;
		case 'b': bufsize = strtoul(optarg, nullptr, 10); break;
		case 'v': verbose = true; break;
		case 'q': quiet = true; break;
		case 'h': help = true; break;
		default: fail = true; break;
		}
	}
	if (help or fail) {
		printf("Usage: %s%s\n", argv[0], USAGE);
		exit(fail? EXIT_FAILURE : EXIT_SUCCESS);
	}

	uchar buf[bufsize];
	streamsize s;
	integer i;
	if(compressing) {
		while(cin.good()) {
			cin.read((char*)buf, bufsize);
			i = bs(buf, s = cin.gcount());
			if(!quiet) {
				if(verbose) {
					cout << i << ' ';
				} else {
					cout.write((char*)&i, sizeof(i));
				}
			}
			cout.write((char*)buf, s);
			if(verbose) cout << endl;
		}
	} else {
		while(cin.good()) {
			if(verbose) {
				cin >> i >> ws;
			} else {
				cin.read((char*)&i, sizeof(i));
			}
			cin.read((char*)buf, bufsize);
			debs(buf, i, s = cin.gcount());
			cout.write((char*)buf, s);
			if(verbose) cout << endl;
		}
	}

	exit(EXIT_SUCCESS);
}

